#!/usr/bin/perl
=pod
my $time_out = 0;
$SIG{ALRM} = sub{$time_out = 1};
print STDERR 'type your password: ';
alarm (5);
my $password = <STDIN>;
alarm (0);

print STDERR "you timed out\n" if $time_out;
=cut
=pod
当定时器期满时，操作系统产生一个ALRM信号，接收到ALRM信号的处理程序将 time_out 设置为 true。
但是Perl自动重启慢的系统调用，包括<>。 尽管闹钟信号，但是仍然在<>调用中，等待用户输入。

这个问题解决方案是使用eval{} 和一个局域ALRM 处理程序来终止读操作。
=cut

print STDERR "TYPE your password: ";
my $password = 
eval {
    local $SIG{ALRM} = sub {die "timeout \n"};
    alarm 5;
    return <STDIN>;
};
alarm 0;
print STDERR "\nyou timed out \n" if $@ =~ /timeout/;

=pod
不同于将ALRM放在程序主体中，我们将它放在eval{}块中。
eval一样设置时钟，并尝试从STDIN读取。如果<>在定时器期满之前返回，则输入的行从eval{}块中返回，并分配给password。

然而，如果定时器在输入前期满，则执行ALRM程序，以一条错误信息 timeout 中止 eval{} 块中的程序，eval{} 块返回undef，
并将 $@ 设置为最后一条错误消息。 如果匹配错误消息则打印一条警告。
=cut